<template>
  <div class="lcd-online-list">
    <div class="lcd-ol-search">
      <AForm layout="inline" :model="search" @finish="query">
        <AFormItem label="名称" name="name">
          <AInput v-model:value="search.name"/>
        </AFormItem>
        <AFormItem label="表名" name="tableName">
          <AInput v-model:value="search.tableName"/>
        </AFormItem>
        <AButton type="primary" @click="query">查询</AButton>
        <AButton @click="add" style="margin-left: 5px">新增</AButton>
        <AButton style="margin-left: 8px" @click="genCode('sql')" type="primary" danger>生成表</AButton>
        <AButton style="margin-left: 8px" @click="genCode('java')">生成后端代码</AButton>
        <AButton style="margin-left: 8px" type="dashed" @click="genCode('vue')" :loading="javaModel.loading">下载前端代码</AButton>
      </AForm>
    </div>
    <div class="icd-ol-list">
      <ATable size="small" :bordered="true" :columns="columns" :row-selection="rowSelection"
              :pagination="pagination" :data-source="source" rowKey="id" :loading="loading">
        <template #existsDesc="{record}">
          <ATag :color="record['tableExists'] ? '#108ee9' : '#87d068'">{{record['tableExists'] ? '已生成' : '未生成'}}</ATag>
        </template>
        <template #action="{record}">
          <ATag class="lcd-ol-tag" color="#108ee9" @click="() => design(record)">编辑</ATag>
          <ATag class="lcd-ol-tag" color="#87d068" @click="() => review(record)">源码预览</ATag>
<!--          <ATag class="lcd-ol-tag" color="#108ee9" @click="() => handleTableName(record)">修改表名</ATag>-->
          <ATag class="lcd-ol-tag" color="red" @click="() => del(record)">删除</ATag>
        </template>
      </ATable>
    </div>
    <AModal title="设置生成条件" v-model:visible="javaModel.visible" ref="javaRef">
      <AForm>
        <AFormItem label="是否覆盖" name="fileOverride">
          <ARadioGroup v-model:value="genModel.fileOverride">
            <ARadio :value="true">是</ARadio>
            <ARadio :value="false">否</ARadio>
          </ARadioGroup>
        </AFormItem>
        <AFormItem label="父菜单" name="menuId" extra="选择父菜单后会生成并导入对应的菜单">
          <ATreeSelect v-model:value="genModel.menuId" style="width: 100%"
                       :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" :allowClear="true"
                       :replaceFields="{key: 'id', title: 'name', value: 'id', children: 'children'}"
                       :tree-data="menus" placeholder="请选择父菜单" tree-default-expand-all>
          </ATreeSelect>
        </AFormItem>
        <AFormItem label="输出到" name="writeTo">
          <ARadioGroup v-model:value="javaModel.writeTo" button-style="solid" @change="writeToChange">
            <ARadio :value="false">生成到指定目录</ARadio>
            <ARadio :value="true">直接生成到项目</ARadio>
          </ARadioGroup>
        </AFormItem>
        <AFormItem label="输出目录" name="outDir" :extra="javaModel.outExtra">
          <AInput v-model:value="genModel.outDir" readonly/>
        </AFormItem>
      </AForm>
      <template #footer>
        <div style="text-align: center">
          <AButton type="primary" @click="genSubmit" :loading="javaModel.loading">生成</AButton>
        </div>
      </template>
    </AModal>
    <ADrawer v-model:visible="drawerModel.visible" width="100%" :getContainer="false" :wrap-style="{ position: 'absolute' }">
      <template #title>
        <span>源码预览</span>
      </template>
      <a-tabs v-model:activeKey="drawerModel.activeKey" tab-position="right">
        <a-tab-pane key="vue" tab="vue"><pre>{{reviewModel.html}}</pre></a-tab-pane>
        <a-tab-pane key="entity" tab="entity"><pre>{{reviewModel.entity}}</pre></a-tab-pane>
        <a-tab-pane key="dto" tab="dto"><pre>{{reviewModel.dto}}</pre></a-tab-pane>
        <a-tab-pane key="mapper" tab="mapper"><pre>{{reviewModel.mapper}}</pre></a-tab-pane>
        <a-tab-pane key="mapperXml" tab="mapperXml"><pre>{{reviewModel.mapperXml}}</pre></a-tab-pane>
        <a-tab-pane key="service" tab="service"><pre>{{reviewModel.service}}</pre></a-tab-pane>
        <a-tab-pane key="serviceImpl" tab="serviceImpl"><pre>{{reviewModel.serviceImpl}}</pre></a-tab-pane>
        <a-tab-pane key="controller" tab="controller"><pre>{{reviewModel.controller}}</pre></a-tab-pane>
      </a-tabs>
    </ADrawer>
  </div>
</template>

<script>
import {ref, reactive} from "vue";
import Utils from "@/utils/basic.utils";

export default {
  name: "index",
  setup() {
    let menus = ref([]);
    let source = ref([])
    let columns = ref([
      {title: '功能名称', dataIndex: 'name', align: 'center'},
      {title: '表名', dataIndex: 'tableName', align: 'center'},
      {title: '主键', dataIndex: 'primary', align: 'center'},
      {title: '表说明', dataIndex: 'comment', align: 'center'},
      {title: '创建时间', dataIndex: 'createTime', align: 'center'},
      {title: '更新时间', dataIndex: 'updateTime', align: 'center'},
      {title: '生成状态', dataIndex: 'existsDesc', align: 'center', slots: {customRender: 'existsDesc'}},
      {title: '操作', dataIndex: 'action', align: 'center', slots: {customRender: 'action'}},
    ])

    let loading = ref(false)
    let search = reactive({
      name: null,
      tableName: null
    })

    let genModel = reactive({
      outDir: null,
      tables: [],
      menuId: null,
      fileOverride: false
    });
    let javaModel = reactive({
      outDir: '',
      writeTo:false,
      visible: false,
      loading: false,
      outExtra: '',
      tableLoading: false,
      fileOverride: false
    })
    let drawerModel = reactive({
      visible: false,
      activeKey: ''
    })
    let reviewModel = reactive({
      entity: '',
      html: '',
      dto: '',
      mapper: '',
      mapperXml: '',
      service: '',
      serviceImpl: '',
      controller: ''
    })
    let pagination = reactive({total: 0, showSizeChanger: true, pageSizeOptions: ['10', '20', '30', '50', '80']})
    let rowSelection = reactive({
      onChange: (selectedRowKeys, selectedRows) => {
        genModel.tables = selectedRows.map(item => item.tableName);
      }
    })
    return {pagination, rowSelection, source, columns, search, loading, genModel, javaModel, drawerModel, menus, reviewModel}
  },
  created() {
    this.query();
    this.$http.get("/lcd/gen/getOutDir").then(({data, code}) => {
      if(code == 200) {
        this.outDir = data;
        this.genModel.outDir = this.outDir.cusGenDir;
        this.javaModel.outExtra = `父包路径：${data['parentPackage']} 所属模块：${data['moduleName']}`
      }
    }).catch(reason => console.error(reason))
    this.$http.get("/lcd/gen/parent").then(({data, code}) => {
      if(code == 200) {
        this.menus = data;
      }
    }).catch(reason => console.error(reason))
  },
  methods: {
    add() {
      this.$router.push('/lcd/design')
    },
    del(record) {
      this.$msg.confirm(`确定删除功能[${record.name}]`, "删除之后将不能恢复(生成的表不会被删除)").then(() => {
        this.$http.post("/lcd/design/del", [record.id]).then(resp => {
          if(resp.code == 200) {
            this.$msg.successMessage("删除记录成功");
            this.query();
          } else {
            this.$msg.warningMessage(resp.message)
          }
        })
      }). catch(reason => null);
    },
    query() {
      this.loading = true;
      this.$http.get("/lcd/design/view", {params: this.search}).then(resp => {
        if(resp.code == 200) {
          this.source = resp.data['records'];
          this.pagination.total = resp.total
        }
      }).finally(() => this.loading = false);
    },
    design(record) {
      this.$router.push('/lcd/design?id='+record.id)
    },
    review(record) {
      let tableName = record.tableName;
      this.drawerModel.visible = true;
      this.$http.get('/lcd/online/review', {params: {tableName}}).then(resp=>{
        if(resp['code'] == 200) {
          this.reviewModel = resp.data;
          this.drawerModel.activeKey='vue';
        } else {
          this.$msg.warningMessage(resp['message'])
        }
      }).catch(reason => this.$msg.errorMessage(reason))
    },
    genCode(type) {
      if(this.genModel.tables && this.genModel.tables.length > 0) {
        if(type == 'java') {
          this.javaModel.visible = true;
        } else if(type == 'sql') {
          this.$msg.confirmOfWaiting("创建数据表确认", "如果数据库不存在表则创建", () => {
            return new Promise((resolve, reject) => {
              this.$http.post("/lcd/online/tables", this.genModel).then(resp => {
                if(resp.code == 200) {
                  let data = resp['data'];
                  this.$msg.successMessage(`生成表成功数量: [${data['successNum']}], 失败: [${data['errorNum']}]`)
                } else {
                  this.$msg.warningMessage(resp['message']);
                }
              }).catch(reason => console.warn(reason)).finally(() => resolve())
            });
          });
        } else {
          this.javaModel.loading = true;
          this.$http.post('/lcd/online/vue', this.genModel).then(resp=> {
            let {code, message, data} = resp;
            if(code == 200) {
              let blob = Utils.base64toBlob(data, "application/zip")
              let downloadTag = document.createElement("a");
              downloadTag.href = window.URL.createObjectURL(blob);
              downloadTag.download = decodeURIComponent("ivzone.zip");
              // 兼容：某些浏览器不支持HTML5的download属性
              if (typeof downloadTag.download === 'undefined') {
                downloadTag.setAttribute('target', '_blank')
              }
              document.body.appendChild(downloadTag);
              downloadTag.click();
              document.body.removeChild(downloadTag);
              window.URL.revokeObjectURL(downloadTag.href);
            } else {
              this.$msg.errorMessage(message);
            }
          }).finally(() => this.javaModel.loading = false)
        }
      } else {
        this.$msg.warningMessage("请选择要生成的记录", 1)
      }
    },
    genSubmit() {
      this.javaModel.loading = true;
      this.$http.post('/lcd/online/java', this.genModel).then(({data, code, message}) => {
        if(code == 200) {
          this.javaModel.visible = false;
          this.$msg.successMessage(`成功生成代码到[${this.genModel.outDir}]`)
        } else {
          this.$msg.errorMessage(message);
        }
      }).catch(reason => {console.error(reason)})
          .finally(() => this.javaModel.loading = false)
    },
    writeToChange(e) {
      let value = e.target.value;
      if(value) {  // 项目
        let projectRoot = this.outDir.projectRoot ? this.outDir.projectRoot : '';
        this.genModel.outDir = projectRoot + "\\src\\main\\java";
      } else {
        this.genModel.outDir = this.outDir.cusGenDir;
      }
    },
    handleTableName(record) {

    }
  }
}
</script>

<style scoped>
.lcd-online-list {
  padding: 0px 24px;
}
.lcd-ol-search {
  padding: 6px 0px;
}
.lcd-ol-tag {
  cursor: pointer;
}
</style>